/*
 * $Id: GSCCUtil.java,v 1.15 2009/10/22 16:20:42 afaichun Exp $
 * 
 * Copyright (C) 2006 General Electric Company. All Rights Reserved.
 * 
 * This software is the confidential and proprietary information of the General
 * Electric Company (GE). You shall not disclose this software and shall use it
 * only in accordance with the terms of the license agreement you entered into
 * with GE.
 * 
 * GE MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
 * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
 * NON-INFRINGEMENT. GE SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING, OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES.
 */
package com.ge.healthcare.autosc.common.util;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Date;
import java.util.Map;
import java.util.Properties;
import java.util.Vector;

import com.ge.healthcare.autosc.common.ASCLogger;
import com.ge.healthcare.autosc.common.ASCUtil;
import com.ge.healthcare.autosc.common.exceptions.GSCCUtilException;
import com.ge.healthcare.autosc.common.pojo.sysInfo.ConnectivityDetails;
import com.ge.healthcare.autosc.common.pojo.sysInfo.LoginDetails;
import com.ge.healthcare.autosc.common.pojo.sysInfo.SystemDetails;
import com.ge.med.service.mc.exceptions.MCDataSourceException;
import com.ge.med.service.stp.dataaccessapi.DataItemException;
import com.ge.med.service.stp.dataaccessapi.DataSourceException;
import com.ge.med.service.stp.gsccmw.clientif.ChronologyDataItem;
import com.ge.med.service.stp.gsccmw.clientif.ConnectivityDataItem;
import com.ge.med.service.stp.gsccmw.clientif.ConnectivityItemKey;
import com.ge.med.service.stp.gsccmw.clientif.GSCCDataSource;
import com.ge.med.service.stp.gsccmw.clientif.LoginDataItem;
import com.ge.med.service.stp.gsccmw.clientif.LoginIterator;
import com.ge.med.service.stp.gsccmw.clientif.SystemDetailsDataItem;
import com.ge.med.service.stp.gsccmw.clientif.SystemDetailsItemKey;
import com.ge.med.service.stp.gsccmw.clientif.SystemIDDataItem;
import com.ge.med.service.stp.gsccmw.clientif.SystemIDIterator;

/**
 * @author 212042764
 * 
 */
public class GSCCUtil {
	public static final int COMMENT_LENGTH = 4000;
	public static final String COMPLETION_CODE = "completion.code";
	public static final String APPLICATION = "application";
	public static final String ATTEMPT_NUM = "attempt.num";
	public static final String PLATFORM = "platform";
	public static final String COMMENT = "comment";
	public static final String TYPE_ID = "type.id";
	public static final String RFS_NUMBER = "rfs.number";
	public static final String LOGIN_ID = "login.id";
	public static final String SYSTEM_ID = "system.id";
	private static GSCCDataSource gsccDataSource = null;
	private static final String GSCC_CONFIG_FILE = ApplicationInfo.getInstance()
		.getProperty(PropertyConstants.GSCC_MIDDLEWARE_CONFIG_FILE, "/autosc/runtime/env/mw.ini");
	private static final char SPACE = ' ';
	private static final char NEW_LINE = '\n';
	/**
	 * Default RFS Number
	 */
	public static final String CHRON_DEFAULT_RFS_NUMBER = "00000000";
	

	/**
	 * Gets GSCC Data source Handle
	 * 
	 * @throws DataSourceException
	 * @throws FileNotFoundException
	 * 
	 * @throws InValidVOException
	 *             - GSCC Client properties couldn't be found
	 * @throws EDSException
	 *             - Failed to instantiate GSCC Client properties
	 */
	public static void getGSCCDataSource() throws DataSourceException,
			FileNotFoundException {
		StringBuffer gsccMwPropFile = new StringBuffer();
		gsccMwPropFile.append(GSCC_CONFIG_FILE);
		BufferedInputStream streamGSCCMwProps = null;
		try {
			streamGSCCMwProps = new BufferedInputStream(new FileInputStream(
					gsccMwPropFile.toString()));
			gsccDataSource = new GSCCDataSource(streamGSCCMwProps);

		} finally {
			ASCFileHandler.closeInputStream(streamGSCCMwProps);
		}
	}

	/**
	 * Add Chronology in the GSCC.
	 * 
	 * @throws EDSException
	 * @exception MCDataSourceException
	 *                for GSCC & RMI related errors.
	 */
	public static void addChronology(Map<String, String> hmap) {
		String methodName = "addChronology";
		if (ASCUtil.isNullOrEmptyObject(gsccDataSource)) {
			try {
				getGSCCDataSource();
			} catch (FileNotFoundException e) {
				ASCLogger.error(GSCCUtil.class, methodName,
						"Failed to find mw.ini file at " + GSCC_CONFIG_FILE, e);
				gsccDataSource = null;
			} catch (DataSourceException e) {
				ASCLogger.error(GSCCUtil.class, methodName,
						"Failed to get GSCC Datasource for adding chronology",
						e);
				gsccDataSource = null;
			}
		}
		if (ASCUtil.isNullOrEmptyObject(gsccDataSource)) {
			return;
		}
		ChronologyDataItem item = null;
		try {
			item = getItem(hmap);
			if (!ASCUtil.isNullOrEmptyObject(item)) {
				gsccDataSource.addItem(item);
			}
		} catch (Exception ex) {
			ASCLogger.error(GSCCUtil.class, methodName,
					"Failed to Insert in Chronology in GSCC DataBase", ex);
		}
	}

	/**
	 * @param hmap
	 *            - Hashmap containing values to be used to populate
	 *            ChronologyDataItem object
	 * @return - ChronologyDataItem Object to be added to chronology table
	 * @throws DataSourceException
	 *             - EDS Interface Exception
	 * @throws DataItemException
	 *             - EDS Interface Exception
	 */
	private static ChronologyDataItem getItem(Map<String, String> hmap)
			throws DataSourceException, DataItemException {
		String methodName = "getItem";
		String systemId = hmap.get(SYSTEM_ID);
		String loginId = hmap.get(LOGIN_ID);
		String rfsNum = hmap.get(RFS_NUMBER);
		String typeId = hmap.get(TYPE_ID);
		String comment = hmap.get(COMMENT);
		String platform = hmap.get(PLATFORM);
		String attemptNum = hmap.get(ATTEMPT_NUM);
		String application = hmap.get(APPLICATION);
		String completionCode = hmap.get(COMPLETION_CODE);
		ChronologyDataItem item = (ChronologyDataItem) gsccDataSource
				.newItem(ChronologyDataItem.class);
		if (! ASCUtil.isNullOrEmpty(rfsNum)) {
			item.set(ChronologyDataItem.RFS_NUMBER, rfsNum);
		} else {
			item.set(ChronologyDataItem.RFS_NUMBER, CHRON_DEFAULT_RFS_NUMBER);
		}
		if (! ASCUtil.isNullOrEmpty(systemId)) {
			item.set(ChronologyDataItem.SYSTEM_ID, systemId);
		} else {
			ASCLogger
					.error(
							GSCCUtil.class,
							methodName,
							"Please insert an Entry system.id in to the hasMap before calling addChronology");
			return null;
		}
		if (! ASCUtil.isNullOrEmpty(loginId)) {
			item.set(ChronologyDataItem.LOGIN_ID, loginId);
		} else {
			ASCLogger
					.error(GSCCUtil.class, methodName,
							"Please insert an Entry login.id in to the hasMap before calling addChronology");
			return null;
		}
		if (comment != null) {
			comment = comment.replace(NEW_LINE,
					SPACE);
			if ( comment.length() > GSCCUtil.COMMENT_LENGTH ){
				comment = comment.substring(0, GSCCUtil.COMMENT_LENGTH);
			}
			item.set(ChronologyDataItem.COMMENT, comment);
		}
		if (typeId != null) {
			item.set(ChronologyDataItem.TYPE_ID, typeId);
		}
		if (platform != null) {
			item.set(ChronologyDataItem.PLATFORM, platform);
		}
		if (attemptNum != null) {
			item.set(ChronologyDataItem.ATTEMPT_NUM, (new Integer(attemptNum)));
		}
		if (application != null) {
			if ( application.length() > 20 ){
				application = application.substring(0, 20);
			}
			item.set(ChronologyDataItem.APPLICATION, application);
		}
		if (completionCode != null) {
			item.set(ChronologyDataItem.COMPLETION_STATUS, completionCode);
		}
		item.set(ChronologyDataItem.CREATE_DATE, new Date());
		return item;
	}
	
	/**
	 * Returns the list of logins and passwords for a system id.
	 *
	 * @param The system id for which the login information is desired.
	 *
	 * @return A collection of LoginsForSystemId.
	 *
	 * @exception Throwable Thrown by the middleware indicating
	 *  a problem occured. This is passed up to the caller.
	 */
	public static Vector<LoginDetails> getLoginDetailsForSystemId(String systemId) 
		throws GSCCUtilException {
		String methodName = "getLoginDetailsForSystemId";
		Vector<LoginDetails> loginDetails = new Vector<LoginDetails>();
		try {
			getGSCCDataSource();
		} catch (FileNotFoundException e) {
			ASCLogger.error(GSCCUtil.class, methodName,
					"Failed to find mw.ini file at " + GSCC_CONFIG_FILE, e);
			gsccDataSource = null;
		} catch (DataSourceException e) {
			ASCLogger.error(GSCCUtil.class, methodName,
					"Failed to get GSCC Datasource for getting login details for system Id" +
					systemId, e);
			gsccDataSource = null;
		}
		
		if (ASCUtil.isNullOrEmptyObject(gsccDataSource)) {
			ASCLogger.error(GSCCUtil.class, methodName, 
					"Severe system error: Unable to obtain datasource to GSCC. System Id" +
					systemId);
			throw new GSCCUtilException(
					"Severe system error: Unable to obtain datasource to GSCC. System Id" +
					systemId);
		}

		try {
			Properties prop = new Properties();
			prop.put(LoginDataItem.SYSTEM_ID, systemId);
			LoginIterator logins = 
				(LoginIterator)gsccDataSource.getItems(LoginDataItem.class, prop);
	
			if ( logins != null )
	        {
	            while ( logins.hasNext() )
	            {
	                LoginDataItem login = (LoginDataItem) logins.next();
	                loginDetails.add( new LoginDetails(login));
	            }
	        }
		} catch (DataSourceException dse) {
			throw new GSCCUtilException(
					"Unable to get login info. System Id=" + systemId, dse);
		} catch (DataItemException die) {
			throw new GSCCUtilException(
					"Unable to get login info. System Id=" + systemId, die);
		}
        return loginDetails;
	}
	
	/**
	 * Returns the connectivity details for a system id.
	 *
	 * @param The system id for which the login information is desired.
	 *
	 * @return A Vector containing zero or more ConnectivityDetails.
	 *
	 * @exception Throwable Thrown by the middleware indicating
	 *  a problem occured. This is passed up to the caller.
	 */
	public static Vector<ConnectivityDetails> getConnectivityDetailsForSystemId( String systemId )
		throws GSCCUtilException {
		String methodName= "connectivityDetailsForSystemId";
		try {
			getGSCCDataSource();
		} catch (FileNotFoundException e) {
			ASCLogger.error(GSCCUtil.class, methodName,
					"Failed to find mw.ini file at " + GSCC_CONFIG_FILE, e);
			gsccDataSource = null;
		} catch (DataSourceException e) {
			ASCLogger.error(GSCCUtil.class, methodName,
				"Failed to get GSCC Datasource for getting connectivity details for system" + 
				systemId, e);
			gsccDataSource = null;
		}

		if (ASCUtil.isNullOrEmptyObject(gsccDataSource)) {
			ASCLogger.error(GSCCUtil.class, methodName, 
					"Severe system error: Unable to obtain datasource to GSCC. System Id" +
					systemId);
			throw new GSCCUtilException(
					"Severe system error: Unable to obtain datasource to GSCC. System Id" +
					systemId);
		}
		
        Vector<ConnectivityDetails> connectivityDetails = new Vector<ConnectivityDetails>();
        ConnectivityItemKey key = new ConnectivityItemKey(systemId);
        ConnectivityDataItem item =
          (ConnectivityDataItem)gsccDataSource.getItem( ConnectivityDataItem.class, key );
        
        try {
        	if (! ASCUtil.isNullOrEmptyObject(item)){
        		connectivityDetails.add( new ConnectivityDetails( item ) );
        	}
        } catch (DataItemException die) {
        	ASCLogger.error(GSCCUtil.class, methodName, 
        			"Failed to get connectivity details for systemId " + systemId, die);
        	throw new GSCCUtilException(
			"Failed to get connectivity details for systemId " + systemId, die);
        }
        return connectivityDetails;
	}
	
	/**
	 * Connects to the middleware and gets the system information. A
	 *  SystemDetails object is instantiated which will be populated with the
	 *  information returned back from GSCC.
	 *
	 * @param The system ID for which information is required.
	 *
	 * @return The system details object containing system information.
	 *
	 * @exception Throwable Thrown by the middleware indicating
	 *  a problem occured. This is passed up to the caller.
	 */
	public static SystemDetails getSystemDetailsForSystemId(String systemId)
		throws GSCCUtilException {
		String methodName= "connectivityDetailsForSystemId";
		try {
			getGSCCDataSource();
		} catch (FileNotFoundException e) {
			ASCLogger.error(GSCCUtil.class, methodName,
					"Failed to find mw.ini file at " + GSCC_CONFIG_FILE, e);
			gsccDataSource = null;
		} catch (DataSourceException e) {
			ASCLogger.error(GSCCUtil.class, methodName,
				"Failed to get GSCC Datasource for getting system details for system" + 
				systemId, e);
			gsccDataSource = null;
		}
		
		if (ASCUtil.isNullOrEmptyObject(gsccDataSource)) {
			ASCLogger.error(GSCCUtil.class, methodName, 
					"Severe system error: Unable to obtain datasource to GSCC. System Id" +
					systemId);
			throw new GSCCUtilException(
					"Severe system error: Unable to obtain datasource to GSCC. System Id" +
					systemId);
		}
		
		SystemDetailsItemKey key =
			new SystemDetailsItemKey(systemId.toUpperCase());
		SystemDetailsDataItem item =
			(SystemDetailsDataItem)	gsccDataSource.getItem(SystemDetailsDataItem.class,
			                                     key );
		
		if (ASCUtil.isNullOrEmptyObject(item)){
			return null;
		}
		SystemDetails details = null;
		
		try
		{
			details = new SystemDetails(item);
		}
		catch (DataItemException die)
		{
        	ASCLogger.error(GSCCUtil.class, methodName, 
        			"Failed to get system details for systemId " + systemId, die);
        	throw new GSCCUtilException(
			"Failed to get system details for systemId " + systemId, die);		
        }
		return details;
	}
	
	/**
	 * Connects to the middleware and gets the system information. A
	 *  SystemDetails object is instantiated which will be populated with the
	 *  information returned back from GSCC.
	 *
	 * @param The IP Address for which information is required.
	 *
	 * @return A vector containing zero or more SystemDetails objects.
	 *
	 * @exception Throwable Thrown by the middleware indicating
	 *  a problem occured. This is passed up to the caller.
	 */
	public static Vector<SystemDetails> getSystemDetailsForIPAddress(String ipAddress)
		throws GSCCUtilException {
        Vector<SystemDetails> systems = new Vector<SystemDetails>();
		String methodName= "getSystemDetailsForIPAddress";
		try {
			getGSCCDataSource();
		} catch (FileNotFoundException e) {
			ASCLogger.error(GSCCUtil.class, methodName,
					"Failed to find mw.ini file at " + GSCC_CONFIG_FILE, e);
			gsccDataSource = null;
		} catch (DataSourceException e) {
			ASCLogger.error(GSCCUtil.class, methodName,
				"Failed to get GSCC Datasource for getting system details for IP address" + 
				ipAddress, e);
			gsccDataSource = null;
		}
		
		if (ASCUtil.isNullOrEmptyObject(gsccDataSource)) {
			ASCLogger.error(GSCCUtil.class, methodName, 
					"Severe system error: Unable to obtain datasource to GSCC. IP address" +
					ipAddress);
			throw new GSCCUtilException(
					"Severe system error: Unable to obtain datasource to GSCC. IP address" +
					ipAddress);
		}
		
		Properties prop = new Properties();
		prop.put(SystemIDDataItem.IP_ADDRESS, ipAddress);
		String errMsg = "Error getting system detail for IP address " + ipAddress;
		try {
			SystemIDIterator systemIds =
				(SystemIDIterator) gsccDataSource.getItems(SystemIDDataItem.class, prop);
			while ( systemIds.hasNext() )
			{
	            SystemIDDataItem aSystem = (SystemIDDataItem) systemIds.next();
	
	            SystemDetailsItemKey key = new SystemDetailsItemKey( aSystem.getSystemId() );
	
				SystemDetailsDataItem systemDetails =
	                            (SystemDetailsDataItem)
	                                gsccDataSource.getItem(SystemDetailsDataItem.class, key);
				if (!ASCUtil.isNullOrEmptyObject(systemDetails)){
					systems.add(new SystemDetails(systemDetails));
				}
			}
		} catch (DataSourceException dse) {
			ASCLogger.error(GSCCUtil.class, methodName, errMsg, dse);
			throw new GSCCUtilException(errMsg, dse);
		} catch (DataItemException die) {
			ASCLogger.error(GSCCUtil.class, methodName, errMsg, die);
			throw new GSCCUtilException(errMsg, die);
		}
        return systems;
	}
	
	public static SystemDetails getSystemDetailsForUsnAndIPAddress(String usn, String ipAddress)
		throws GSCCUtilException {
	    SystemDetails aSystem = null;
		String methodName= "getSystemDetailsForUsnAndIPAddress";
		try {
			getGSCCDataSource();
		} catch (FileNotFoundException e) {
			ASCLogger.error(GSCCUtil.class, methodName,
					"Failed to find mw.ini file at " + GSCC_CONFIG_FILE, e);
			gsccDataSource = null;
		} catch (DataSourceException e) {
			ASCLogger.error(GSCCUtil.class, methodName,
				"Failed to get GSCC Datasource for getting system details for IP address" + 
				ipAddress, e);
			gsccDataSource = null;
		}
		
		if (ASCUtil.isNullOrEmptyObject(gsccDataSource)) {
			ASCLogger.error(GSCCUtil.class, methodName, 
					"Severe system error: Unable to obtain datasource to GSCC. IP address" +
					ipAddress);
			throw new GSCCUtilException(
					"Severe system error: Unable to obtain datasource to GSCC. IP address" +
					ipAddress);
		}
		
		Properties prop = new Properties();
		prop.put(SystemIDDataItem.IP_ADDRESS, ipAddress);
		String errMsg = "Error getting system detail for IP address " + ipAddress;
		try {
			SystemIDIterator systemIds =
				(SystemIDIterator) gsccDataSource.getItems(SystemIDDataItem.class, prop);
			while ( systemIds.hasNext() )
			{
	            SystemIDDataItem aSystemItem = (SystemIDDataItem) systemIds.next();
	            SystemDetailsItemKey key = new SystemDetailsItemKey( aSystemItem.getSystemId() );
				SystemDetailsDataItem systemDetails =
	                            (SystemDetailsDataItem)
	                                gsccDataSource.getItem(SystemDetailsDataItem.class, key);
				if(systemDetails.getUSN().equals(usn)) {
					aSystem = new SystemDetails(systemDetails);
					break;
				}
			}
		} catch (DataSourceException dse) {
			ASCLogger.error(GSCCUtil.class, methodName, errMsg, dse);
			throw new GSCCUtilException(errMsg, dse);
		} catch (DataItemException die) {
			ASCLogger.error(GSCCUtil.class, methodName, errMsg, die);
			throw new GSCCUtilException(errMsg, die);
		}
	    return aSystem;
	}
}
